package cn.ztuo.bitrade.controller;

import cn.ztuo.bitrade.constant.BooleanEnum;
import cn.ztuo.bitrade.constant.MemberLevelEnum;
import cn.ztuo.bitrade.entity.*;
import cn.ztuo.bitrade.entity.transform.AuthMember;
import cn.ztuo.bitrade.service.*;
import cn.ztuo.bitrade.util.BigDecimalUtils;
import cn.ztuo.bitrade.util.CheckTraderOrderUtil;
import cn.ztuo.bitrade.util.ContractUtils;
import cn.ztuo.bitrade.util.MessageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.ztuo.bitrade.constant.SysConstant.SESSION_MEMBER;
import static cn.ztuo.bitrade.util.BigDecimalUtils.compare;

/**
 * 合约订单控制器
 */
@Slf4j
@RestController
@RequestMapping("/contract-order")
public class ContractOrderController {
    @Autowired
    private ContractCoinService contractCoinService;
    @Autowired
    private ContractWalletService walletService;
    @Autowired
    private ContractOrderService contractOrderService;
    @Autowired
    private LocaleMessageSourceService msService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    @Autowired
    private ContractPositionService positionService;
    @Value("${exchange.max-cancel-times:-1}")
    private int maxCancelTimes;
    @Autowired
    private ContractOrderDetailService contractOrderDetailService;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private BourseProductManagerService productManagerService;

    /**
     * @param authMember   缓存的用户信息
     * @param direction    买卖的方向 BUY
     * @param symbol       合约名称 BTC/USDT
     * @param price        价格 9618 .260700
     *                     //     * @param amount        数量  1
     * @param type         挂单类型  LIMIT_PRICE
     * @param triggerPrice 触发价
     * @param multiple     倍数
     *                     //     * @param maintain      维持保证金
     *                     //     * @param start         起始保证金
     *                     //     * @param locationValue 仓位价值
     * @param nowp         合约张数
     * @return
     */
    @RequestMapping("/add")
    public MessageResult addcontractOrder(@SessionAttribute(SESSION_MEMBER) AuthMember authMember,
                                          ContractOrderDirection direction,
                                          String symbol,
                                          BigDecimal price,
                                          ContractOrderType type,
                                          BigDecimal triggerPrice,
                                          BigDecimal multiple,
                                          Integer stopType,
                                          BigDecimal nowp,
                                          ContractEnumType.ContractOrderPositionFlag positionFlag,
                                          ContractEnumType.ContractOrderPositionOprationType positionOprationType) throws ParseException {

        log.info("用户下单authMember={},direction={},symbol={},price={},amount={},type={},triggerPrice={}"
                , authMember, direction, symbol, price, type, triggerPrice);
        ContractOrder order = null;
        ContractOrderPositionType positionType = null;
        //判断该产品是否关闭
        BourseProductManager productManager = productManagerService.getByProductCode("0300");
        if(productManager.getStatus()==0){
            return MessageResult.error(500, msService.getMessage("PRODUCT_CLOSE"));
        }
        //判断买卖方向  挂单类型不能为空
        if (direction == null || type == null) {
            return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
        }
        if (nowp == null || nowp.scale() != 0||nowp.compareTo(BigDecimal.ZERO)<=0) {
            return MessageResult.error("合约数量格式不对,请输入正整数!");
        }

        //判断是否实名认证
        Member member = memberService.findOne(authMember.getId());
        if (member.getMemberLevel() == MemberLevelEnum.GENERAL) {
            return MessageResult.error(500, "请先进行实名认证");
        }
        //是否被禁止交易
        if (member.getTransactionStatus().equals(BooleanEnum.IS_FALSE)) {
            return MessageResult.error(500, msService.getMessage("CANNOT_TRADE"));
        }
        order = new ContractOrder();
        //判断交易对是否存在 并且状态是否可用
        ContractCoin bySymbol = contractCoinService.findBySymbol(symbol);
        if (bySymbol == null || bySymbol.getEnable() == 0) {
            return MessageResult.error(500, msService.getMessage("NONSUPPORT_COIN"));
        }
        String baseSymbol = bySymbol.getBaseSymbol();
        String coinSymbol = bySymbol.getCoinSymbol();
        //非市价合约 价格必须大于0
        if (price.compareTo(BigDecimal.ZERO) <= 0 && type != ContractOrderType.MARKET_PRICE) {
            return MessageResult.error(500, msService.getMessage("EXORBITANT_PRICES"));
        } else {
            //判断交易目标币种的数量,并且必须大于0
            //数量不能小于0
            if (bySymbol.getMinVolume().multiply(nowp).compareTo(BigDecimal.ZERO) <= 0) {
                return MessageResult.error(500, msService.getMessage("NUMBER_OF_ILLEGAL"));
            }
        }
        if(type==ContractOrderType.MARKET_PRICE){
            price = BigDecimal.ZERO;
        }
        if(type==ContractOrderType.MARKET_PRICE){
            String serviceName = "service-contract-trade";
            String url = "http://" + serviceName + "/contract/monitor/getNewoPrice";
            JSONObject map = new JSONObject();
            map.put("symbol", symbol);
            map.put("direction", direction);
            MessageResult mr = restTemplate.postForObject(url, map, MessageResult.class);
            if(mr.getCode()!=0){
                return MessageResult.error("系统忙,请稍后再试!");
            }
            price =new BigDecimal(mr.getData().toString()) ;
        }
        //判断买方向  计划合约 并确定 开多  开空类型
        if (type == ContractOrderType.CHECK_FULL_STOP) {
            if (stopType == null || (stopType != 1 && stopType != 2)) {
                return MessageResult.error("止盈止损类型不能为空");
            }
            positionFlag = ContractEnumType.ContractOrderPositionFlag.throwout;
        }
        //平仓标记 0: (挂单 非平仓) 1:平仓
        if (positionFlag == null) {
            positionFlag = ContractEnumType.ContractOrderPositionFlag.designate;
        }
        if (direction == ContractOrderDirection.BUY) {
//            if (type == ContractOrderType.CHECK_FULL_STOP || type == ContractOrderType.PLAN_PRICE) {
//                // 触发价不允许小于买入价
//                if (triggerPrice == null || triggerPrice.compareTo(price) > 0) {
//                    return MessageResult.error("触发价不允许大于买入价");
//                }
//            }
            if (triggerPrice == null || triggerPrice.compareTo(BigDecimal.ZERO) == 0) {
                order.setTriggerPrice(null);
            }
            if (positionFlag == ContractEnumType.ContractOrderPositionFlag.designate) {
                positionType = ContractOrderPositionType.RISE;
            }
            if (positionFlag == ContractEnumType.ContractOrderPositionFlag.throwout) {
                if (type == ContractOrderType.PLAN_PRICE) {
                    return MessageResult.error(500, msService.getMessage("BUY_CHECK_FULL_ILLEGAL"));
                }
                //平仓操作类型  0:主动平仓 1:强平
                positionType = ContractOrderPositionType.FALL;
                if (positionOprationType == null) {
                    positionOprationType = ContractEnumType.ContractOrderPositionOprationType.initiative;
                }
            }
        }

        if (direction == ContractOrderDirection.SELL) {
//            if (type == ContractOrderType.CHECK_FULL_STOP || type == ContractOrderType.PLAN_PRICE) {
//                // 触发价不允许小于买入价
//                if (triggerPrice.compareTo(price) < 0) {
//                    return MessageResult.error("触发价不得小于执行价");
//                }
//            }
            if (positionFlag == ContractEnumType.ContractOrderPositionFlag.designate) {
                positionType = ContractOrderPositionType.FALL;
            }
            if (positionFlag == ContractEnumType.ContractOrderPositionFlag.throwout) {
                if (type == ContractOrderType.PLAN_PRICE) {
                    return MessageResult.error(500, msService.getMessage("BUY_CHECK_FULL_ILLEGAL"));
                }
                positionType = ContractOrderPositionType.RISE;
            }
        }
        //委托数量和精度控制
        BigDecimal amount = BigDecimalUtils.mul(bySymbol.getMinVolume(), nowp);

        if (price.compareTo(BigDecimal.ZERO) <= 0 ) {
            return MessageResult.error(500, msService.getMessage("EXORBITANT_PRICES"));
        }
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            return MessageResult.error(500, msService.getMessage("NUMBER_OF_ILLEGAL"));
        }
        ContractWallet exCoinWallet = walletService.findByMemberId(member.getId());
        if (exCoinWallet == null) {
            return MessageResult.error(500, msService.getMessage("CONTRACT_ACOUNT_NO"));
        }
        if (exCoinWallet.getIsLock() == 1) {
            return MessageResult.error(500, msService.getMessage("WALLET_LOCKED"));
        }

        //平仓操作成交量范围控制
        if (positionFlag == ContractEnumType.ContractOrderPositionFlag.throwout) {
            multiple = new BigDecimal(100);
            ContractPosition position = positionService.getByPositionTypeAndSymbolAndMemberId(positionType, symbol, authMember.getId());
            if (position == null ||position.getContractOccupyNum()<=0|| !BigDecimalUtils.compare(new BigDecimal(position.getContractOccupyNum()), nowp)) {
                if(position==null){
                    return MessageResult.error("暂无仓位,无法进行平仓操作!");
                }else{
                    return MessageResult.error(500, "成交数量至多为" + (new BigDecimal(position.getContractOccupyNum())).toString());
                }
            }
            if(type==ContractOrderType.CHECK_FULL_STOP){
                if((stopType==1&&direction==ContractOrderDirection.BUY)||(stopType==2&&direction==ContractOrderDirection.SELL)){
                    if(triggerPrice.compareTo(position.getPositionAvgPrice())>=0||price.compareTo(position.getPositionAvgPrice())>=0){
                        return MessageResult.error("触发价与执行价必须小于持仓平均价!");
                    }
                    if((triggerPrice.compareTo(position.getPredictForcePriceGain())<0||price.compareTo(position.getPredictForcePriceGain())<0)&&(stopType==1&&direction==ContractOrderDirection.BUY)){
                        return MessageResult.error("触发价与执行价必须大于"+position.getPredictForcePriceGain().toString());
                    }
//                    if((triggerPrice.compareTo(position.getPredictForcePriceGain())<0||price.compareTo(position.getPredictForcePriceGain())<0)&&(stopType==2&&direction==ContractOrderDirection.SELL)){
//                        return MessageResult.error("触发价与执行价必须大于"+position.getPredictForcePriceGain().toString());
//                    }
                }
                if((stopType==2&&direction==ContractOrderDirection.BUY)||(stopType==1&&direction==ContractOrderDirection.SELL)){
                    if(triggerPrice.compareTo(position.getPositionAvgPrice())<=0||price.compareTo(position.getPositionAvgPrice())<=0){
                        return MessageResult.error("触发价与执行价必须大于持仓平均价!");
                    }
                    if((triggerPrice.compareTo(position.getPredictForcePriceGain())>0||price.compareTo(position.getPredictForcePriceGain())>0)&&(stopType==1&&direction==ContractOrderDirection.SELL)){
                        return MessageResult.error("触发价与执行价必须小于"+position.getPredictForcePriceGain().toString());
                    }
                }
            }

            BigDecimal start = nowp.divide(new BigDecimal(position.getContractOccupyNum()), 8, BigDecimal.ROUND_DOWN).multiply(position.getUseableBond());
            order.setStart(start);
            if(StringUtils.isNotBlank(position.getCurrentMultiple())){
                multiple=new BigDecimal(position.getCurrentMultiple());
            }
            //判断余额是否足够保证金
//            if (!ContractUtils.isBalanceEnoughBond(authMember.getId(), bySymbol, order.getStart(),positionFlag)) {
//                return MessageResult.error("可用余额不足,无法冻结手续费用!");
//            }
        }
        //挂单操作成交量范围控制
        if (positionFlag == ContractEnumType.ContractOrderPositionFlag.designate) {
            if (multiple == null || multiple.compareTo(BigDecimal.ZERO) <= 0) {
                return MessageResult.error("杠杆倍数不能为空");
            }
            //最小成交额控制
//            if (amount.compareTo(bySymbol.getMinVolume()) < 0) {
//                return MessageResult.error(500, "成交额至少为" + bySymbol.getMinVolume());
//            }
            //最大成交额控制
//            if (amount.compareTo(bySymbol.getMaxVolume()) > 0) {
//                return MessageResult.error(500, "成交数量至多为" + bySymbol.getMaxVolume());
//            }
            //只有普通挂单才冻结相应保证金;
            //起始保证金
            JSONObject map = ContractUtils.getStart(price, amount, bySymbol, nowp, authMember.getId(), multiple);
            BigDecimal start = map.getBigDecimal("start");
            String startRate = map.getString("startRate");
            log.info("====================起始保证金:  " + start);
            if (!compare(exCoinWallet.getBalance(), start)) {
                return MessageResult.error("委托数量大于最大可开手数");
            }
            //维持保证金
            JSONObject maintainMap = ContractUtils.getMaintain(amount, bySymbol, nowp, authMember.getId(), multiple);
            BigDecimal maintain = maintainMap.getBigDecimal("maintain");
            String maintainRate = maintainMap.getString("maintainRate");
            log.info("====================维持保证金:  " + maintain);
//            if (!compare(exCoinWallet.getBalance(), maintain)) {
////                return MessageResult.error(500, msService.getMessage("INSUFFICIENT_COIN"));
////            }
            //判断余额是否足够保证金
            order.setStart(start);
            order.setStartRate(startRate);
            order.setMaintain(maintain);
            order.setMaintainRate(maintainRate);
            if (!ContractUtils.isBalanceEnoughBond(authMember.getId(), bySymbol, order.getStart(),positionFlag)) {
                return MessageResult.error("余额不足");
            }
        }


        //TODO
        if (stopType != null) {
            order.setStopType(stopType);
        }
        order.setAmount(amount);
        order.setTriggerPrice(triggerPrice);
        order.setSymbol(symbol);
        order.setBaseSymbol(baseSymbol);
        order.setCoinSymbol(coinSymbol);

        order.setPositionValue(BigDecimalUtils.mul(amount, price));
        order.setNowp(nowp);
        order.setDirection(direction);
        order.setMemberId(authMember.getId());

        order.setStatus(ContractOrderStatus.NODEAL);
        order.setType(type);
        order.setMultiple(multiple);
        order.setPositionType(positionType);
        order.setPositionFlag(positionFlag);
        order.setPositionOprationType(positionOprationType);
        order.setOrderResource(ContractOrderResource.CUSTOMER);
        order.setTurnover(BigDecimal.ZERO);
        order.setSetTime(Calendar.getInstance().getTimeInMillis());
        order.setPrice(price);
        BigDecimal fee = ContractUtils.getFee(authMember.getId(), bySymbol,order.getAmount().multiply(order.getPrice()));
        order.setFee(fee);
        log.info("开始添加挂单=====================================================");

        if(order.getType()==ContractOrderType.LIMIT_PRICE&&(order.getStart().compareTo(BigDecimal.ZERO)<=0||order.getNowp().compareTo(BigDecimal.ZERO)<=0)){
            return MessageResult.error(500, "系统忙请稍后再试!");
        }


        MessageResult mr = contractOrderService.addOrder(member.getId(), order);
        log.info("添加挂单成功=====================================================");
        if (mr.getCode() != 0) {
            return MessageResult.error(500, "提交订单失败:" + mr.getMessage());
        }
        //计划单
        if (type == ContractOrderType.CHECK_FULL_STOP || type == ContractOrderType.PLAN_PRICE) {
            //止盈止损单发送到其他地方
            kafkaTemplate.send("contract-waiting-order", symbol, JSON.toJSONString(order));
        } else {
            //市价直接发送到 发送消息至Contract系统
            kafkaTemplate.send("contract-order", symbol, JSON.toJSONString(order));
        }
        log.info("结束le ================================");
        MessageResult result = MessageResult.success(msService.getMessage("SUCCESS"));
        result.setData(order.getOrderId());
        return result;
    }

    /**
     * 历史委托
     *
     * @param member   缓存里面的会员信息
     * @param symbol   交易对
     * @param pageNo
     * @param pageSize
     * @return
     * @Param status 交易状态 name  如果是all 查询全部
     * @SessionAttribute是用于获取已经存储的session数据
     */
    //根据用户id  交易对查询 挂单的历史记录
    @RequestMapping("/history")
    public Page<ContractOrder> historyOrder(@SessionAttribute(SESSION_MEMBER) AuthMember member, String symbol, String status, int pageNo, int pageSize) {
        Page<ContractOrder> page = contractOrderService.findHistory(member.getId(), symbol, pageNo, pageSize);
        ContractCoin coin = contractCoinService.findBySymbol(symbol);
        page.getContent().forEach(contractOrder -> {
            contractOrder.setPriceStr(contractOrder.getPrice().setScale(coin.getBaseCoinScale(), RoundingMode.DOWN).toPlainString());
            contractOrder.setAmountStr(contractOrder.getAmount().setScale(coin.getCoinScale(), RoundingMode.DOWN).toPlainString());
            //获取交易成交详情
            contractOrder.setDetail(contractOrderDetailService.findAllByOrderId(contractOrder.getOrderId()));
        });
        return page;
    }

    /**
     * 当前委托订单列表
     *
     * @param member
     * @param pageNo
     * @param pageSize
     * @param type     1:当前委托 2:计划委托 3:已完成 4:撤销纪律 5:止盈止损
     * @return
     */
    @RequestMapping("/current")
    public Page<ContractOrder> currentOrder(@SessionAttribute(SESSION_MEMBER) AuthMember member, String symbol, Integer type, int pageNo, int pageSize) {
        Page<ContractOrder> page = null;
        if (type == null) {
            type = 1;
        }
        switch (type) {
            case 1:
                page = contractOrderService.findPageCurrent(member.getId(), symbol, pageNo, pageSize);
                break;
            case 2:
                page = contractOrderService.findPageStop(member.getId(), symbol, pageNo, pageSize, ContractOrderStatus.WAITING_TRIGGER, ContractOrderType.PLAN_PRICE);
                break;
            case 3:
                page = contractOrderService.findPageByStatus(member.getId(), symbol, pageNo, pageSize, ContractOrderStatus.COMPLETED);
                break;
            case 4:
                page = contractOrderService.findPageByStatus(member.getId(), symbol, pageNo, pageSize, ContractOrderStatus.CANCELED);
                break;
            case 5:
                page = contractOrderService.findPageStop(member.getId(), symbol, pageNo, pageSize, ContractOrderStatus.WAITING_TRIGGER, ContractOrderType.CHECK_FULL_STOP);
                break;
            default:
                break;
        }
        page.getContent().stream().forEach(contractOrder -> {
            //获取交易成交详情
            BigDecimal tradedAmount = BigDecimal.ZERO;
            BigDecimal fee = BigDecimal.ZERO;
            BigDecimal yingKui = BigDecimal.ZERO;
            int tradeNowp = 0;
            List<ContractOrderDetail> details = contractOrderDetailService.findAllByOrderId(contractOrder.getOrderId());
            contractOrder.setDetail(details);
            for (ContractOrderDetail trade : details) {
                fee = fee.add(trade.getFee());
                yingKui = yingKui.add(trade.getYingKui() == null ? BigDecimal.ZERO : trade.getYingKui());
                tradedAmount = tradedAmount.add(trade.getAmount());
                tradeNowp = tradeNowp + trade.getTradeNowp().intValue();
                contractOrder.setPriceStr(trade.getPrice().toPlainString());
                contractOrder.setAmountStr(tradedAmount.toPlainString());
                contractOrder.setPrice(trade.getPrice());
            }
            contractOrder.setTradedAmount(tradedAmount);
            contractOrder.setTradeNowp(tradeNowp);
            contractOrder.setFee(fee);
            contractOrder.setYingKui(yingKui);
            contractOrder.setSubNowp(contractOrder.getNowp().intValue() - tradeNowp);
        });
        return page;
    }


    /**
     * 查询委托成交明细
     *
     * @param member
     * @param orderId
     * @return
     */
    @RequestMapping("/detail/{orderId}")
    public List<ContractOrderDetail> currentOrder(@SessionAttribute(SESSION_MEMBER) AuthMember member, @PathVariable String orderId) {
        return contractOrderDetailService.findAllByOrderId(orderId);
    }

    //撤销订单
    @RequestMapping("/cancel/{orderId}")
    public MessageResult cancelOrder(@SessionAttribute(SESSION_MEMBER) AuthMember member, @PathVariable String orderId) throws Exception {
        ContractOrder order = contractOrderService.findOne(orderId);
        if (order.getMemberId() != member.getId()) {
            return MessageResult.error(500, "禁止操作");
        }
        if (order.getStatus() != ContractOrderStatus.TRADING && order.getStatus() != ContractOrderStatus.WAITING_TRIGGER) {
            return MessageResult.error(500, "订单不在交易");
        }
        if (maxCancelTimes > 0 && contractOrderService.findTodayOrderCancelTimes(member.getId(), order.getSymbol()) >= maxCancelTimes) {
            return MessageResult.error(500, "你今天已经取消了 " + maxCancelTimes + " 次");
        }
        if (order.getType() == ContractOrderType.CHECK_FULL_STOP || order.getType() == ContractOrderType.PLAN_PRICE) {
            //止盈止损取消
            Boolean isExist =  CheckTraderOrderUtil.isWaitingOrderExist(order, restTemplate);
            if (isExist==null) {
                return MessageResult.error("系统忙,请稍后再试!");
            }
            if (order.getStatus() == ContractOrderStatus.WAITING_TRIGGER &&isExist) {
                kafkaTemplate.send("contract-waiting-order-cancel", order.getSymbol(), JSON.toJSONString(order));
            } else {
                // 强制取消
                contractOrderService.forceCancelOrder(order);
            }
        } else {
            Boolean isExist = CheckTraderOrderUtil.isContractOrderExist(order, restTemplate);
            if (isExist==null) {
                return MessageResult.error("系统忙,请稍后再试!");
            }
            if (order.getStatus() == ContractOrderStatus.TRADING && isExist) {
                // 发送消息至contract系统
                kafkaTemplate.send("contract-order-cancel", order.getSymbol(), JSON.toJSONString(order));
            } else {
                // 强制取消
                contractOrderService.forceCancelOrder(order);
            }

        }
        return MessageResult.success(msService.getMessage("SUCCESS"));
    }

    /**
     * 个人中心历史委托
     */
    @RequestMapping("/personal/history")
    public Page<ContractOrder> personalHistoryOrder(@SessionAttribute(SESSION_MEMBER) AuthMember member,
                                                    @RequestParam(value = "symbol", required = false) String symbol,
                                                    @RequestParam(value = "type", required = false) ContractOrderType type,
                                                    @RequestParam(value = "status", required = false) ContractOrderStatus status,
                                                    @RequestParam(value = "startTime", required = false) String startTime,
                                                    @RequestParam(value = "endTime", required = false) String endTime,
                                                    @RequestParam(value = "direction", required = false) ContractOrderDirection direction,
                                                    @RequestParam(value = "pageNo", defaultValue = "1") int pageNo,
                                                    @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) {
        List<ContractOrder> orders = contractOrderService.findAllByMemberId(member.getId());
        List<String> orderIds = orders.stream().map(ContractOrder::getOrderId).collect(Collectors.toList());
        List<ContractOrderDetail> orderDetails = contractOrderDetailService.findByMemberId(orderIds);
        orderIds = orderDetails.stream().map(ContractOrderDetail::getOrderId).collect(Collectors.toList());
        Page<ContractOrder> page = contractOrderService.findPersonalHistory(member.getId(), symbol, type, status, startTime, endTime, direction, pageNo, pageSize, orderIds);
        page.getContent().stream().forEach(contractOrder -> {
            //获取交易成交详情
            BigDecimal tradedAmount = BigDecimal.ZERO;
            BigDecimal fee = BigDecimal.ZERO;
            BigDecimal yingKui = BigDecimal.ZERO;
            int tradeNowp = 0;
            List<ContractOrderDetail> details = contractOrderDetailService.findAllByOrderId(contractOrder.getOrderId());
            contractOrder.setDetail(details);
            for (ContractOrderDetail trade : details) {
                fee = fee.add(trade.getFee());
                yingKui = yingKui.add(trade.getYingKui() == null ? BigDecimal.ZERO : trade.getYingKui());
                tradedAmount = tradedAmount.add(trade.getAmount());
                tradeNowp = tradeNowp + trade.getTradeNowp().intValue();
                contractOrder.setPriceStr(trade.getPrice().toPlainString());
                contractOrder.setAmountStr(tradedAmount.toPlainString());
                contractOrder.setPrice(trade.getPrice());
            }
            contractOrder.setTradedAmount(tradedAmount);
            contractOrder.setTradeNowp(tradeNowp);
            contractOrder.setFee(fee);
            contractOrder.setYingKui(yingKui);
            contractOrder.setSubNowp(contractOrder.getNowp().intValue() - tradeNowp);
        });
        return page;
    }


    /**
     * 个人中心当前委托
     *
     * @param member
     * @param symbol
     * @param type
     * @param startTime
     * @param endTime
     * @param pageNo
     * @param pageSize
     * @return
     */
    @RequestMapping("/personal/current")
    public Page<ContractOrder> personalCurrentOrder(@SessionAttribute(SESSION_MEMBER) AuthMember member,
                                                    @RequestParam(value = "symbol", required = false) String symbol,
                                                    @RequestParam(value = "type", required = false) ContractOrderType type,
                                                    @RequestParam(value = "startTime", required = false) String startTime,
                                                    @RequestParam(value = "endTime", required = false) String endTime,
                                                    @RequestParam(value = "direction", required = false) ContractOrderDirection direction,
                                                    @RequestParam(value = "pageNo", defaultValue = "1") int pageNo,
                                                    @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) {
        Page<ContractOrder> page = contractOrderService.findPersonalCurrent(member.getId(), symbol, type, startTime, endTime, direction, pageNo, pageSize);
        page.getContent().forEach(contractOrder -> {
            //获取交易成交详情
            BigDecimal tradedAmount = BigDecimal.ZERO;
            BigDecimal yingKui = BigDecimal.ZERO;
            BigDecimal turnover = BigDecimal.ZERO;
            List<ContractOrderDetail> details = contractOrderDetailService.findAllByOrderId(contractOrder.getOrderId());
            contractOrder.setDetail(details);
            for (ContractOrderDetail trade : details) {
                tradedAmount = tradedAmount.add(trade.getAmount());
                yingKui = yingKui.add(trade.getYingKui() == null ? BigDecimal.ZERO : trade.getYingKui());
//                turnover = turnover.add(trade.getTurnover());
            }
            contractOrder.setTradedAmount(tradedAmount);
            contractOrder.setYingKui(yingKui);
//            contractOrder.setTurnover(turnover);
        });
        return page;
    }

    /**
     * 资产概要
     */
    @RequestMapping("/gaiYao")
    public Map<String, String> personalCurrentOrder(@SessionAttribute(SESSION_MEMBER) AuthMember member, String symbol) {
        Map<String, String> map = new HashMap<>();
        BigDecimal useableBond = BigDecimal.ZERO;
        BigDecimal dealProfit = BigDecimal.ZERO;
        BigDecimal positionBond = BigDecimal.ZERO;
        BigDecimal orderBond = BigDecimal.ZERO;
        String currentMultiple = null;
        BigDecimal assets = BigDecimal.ZERO;
        ContractWallet wallet = walletService.findByMemberId(member.getId());
        if(wallet==null){
            assets=BigDecimal.ZERO;
            map.put("assets", BigDecimal.ZERO.toPlainString());
            map.put("useableBond", BigDecimal.ZERO.toPlainString());
//        map.put("useableBond",useableBond.toString());
            map.put("dealProfit", BigDecimal.ZERO.toString());
//        map.put("positionBond", positionBond.toPlainString());
            map.put("positionBond",BigDecimal.ZERO.toString());
            map.put("orderBond", BigDecimal.ZERO.toString());
            map.put("currentMultiple", null);
        }else{
            assets = wallet.getBalance().add(wallet.getFrozenBalance());
            List<ContractPosition> positions = positionService.findByMemberIdAndSymbol(member.getId(), symbol);

            for (ContractPosition position : positions) {
                useableBond = useableBond.add(position.getUseableBond());
                dealProfit = dealProfit.add(position.getDealGainLoss());
                positionBond = positionBond.add(position.getHoldingBond());
                currentMultiple = position.getCurrentMultiple();
            }
            List<ContractOrder> orders = contractOrderService.findPageCurrent(member.getId(), symbol);
            for (ContractOrder order : orders) {
                BigDecimal start = order.getStart();
                List<ContractOrderDetail> details = contractOrderDetailService.findAllByOrderId(order.getOrderId());
                for (ContractOrderDetail trade : details) {
                    start = start.subtract(trade.getBond());
                }
                orderBond = orderBond.add(start.add(order.getFee()));
                if(order.getPositionFlag()==ContractEnumType.ContractOrderPositionFlag.throwout){
                    useableBond = useableBond.subtract(order.getFee());
                }
            }
            map.put("assets", assets.toPlainString());
            map.put("useableBond", wallet.getBalance().toPlainString());
//        map.put("useableBond",useableBond.toString());
            map.put("dealProfit", dealProfit.compareTo(BigDecimal.ZERO) == 0 ? "0" : dealProfit.toString());
//        map.put("positionBond", positionBond.toPlainString());
            map.put("positionBond",useableBond.toString());
            map.put("orderBond", orderBond.toString());
            map.put("currentMultiple", currentMultiple);
        }
        return map;
    }
}
